<?php

namespace Renshan\DetectorBundle\Service;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Renshan\DetectorBundle\Entity\Target as TargetEntity;

use Renshan\Http\Request;
use Renshan\Http\Response;
use Renshan\Http\Headers;

use Renshan\DetectorBundle\Entity\Result as ResultEntity;
use Renshan\UserBundle\Service\User as UserService;

class Target
{
    private $container;
    private $target     = null;
    private $results    = [];
    private $user_service;
    private $request_result;

    public function __construct(ContainerInterface $container, UserService $user_service)
    {
        $this->container    = $container;
        $this->user_service = $user_service;
    }

    /**
     *
     * 创建一个探测接口
     *
     * @param   string          $title
     * @param   string          $url
     * @param   string          $method
     * @param   array           $headers
     * @param   array           $parameters
     *
     * @return  TargetEntity    $target
     */
    public function create($title, $url, $method = 'GET', $timing, $headers = [], $parameters = [])
    {
        $target =  new TargetEntity;

        $user = $this->user_service->getUser();

        $target->setTitle($title);
        $target->setUrl($url);
        $target->setMethod($method);
        $target->setTiming($timing);
        $target->setHeaders($headers);
        $target->setParameters($parameters);
        $target->setUser($user);

        $em = $this->container->get('doctrine')->getManager();
        $em->persist($target);
        $em->flush();

        return $target;
    }

    /**
     *
     * 获取所有接口的个数
     *
     * @return integer
     */
    public function count()
    {
        $user = $this->user_service->getUser();
        $query = $this->container->get('doctrine')->getManager()->createQuery("SELECT COUNT(t.id) from Renshan\DetectorBundle\Entity\Target t WHERE t.user = ?1");
        $query->setParameter(1, $user);
        $result = $query->getArrayResult();
        return $result[0][1];
    }

    /**
     *
     * 获取接口的分页数据
     *
     * @param integer $page
     * @param integer $page_size
     *
     * @return array
     */
    public function pagination($page = 1, $page_size = 20)
    {
        $user = $this->user_service->getUser();

        $page_size = $page_size ? $page_size : 20;

        $total = $this->count($user);
        $max_page = ceil($total / $page_size);

        $page = $page < 1 ? 1 : $page;
        $page = $page > $max_page ? $max_page : $page;

        $offset = ($page - 1) * $page_size;

        if ($total != 0) {

            $qb = $this->container->get('doctrine')->getManager()->createQueryBuilder();

            $qb->select('t')
                ->from('Renshan\DetectorBundle\Entity\Target', 't')
                ->where("t.user = ?1")
                ->setFirstResult( $offset )
                ->setMaxResults( $page_size )
                ->setParameter(1, $user);

            $query = $qb->getQuery();

            return [
                'current_page' => (int)$page, 
                'max_page' => (int)$max_page,
                'total' => (int)$total,
                'page_size' => (int)$page_size,
                'data' => $query->getArrayResult()
            ];
        }

        return [
            'current_page' => 1, 
            'max_page' => 1,
            'total' => 0,
            'page_size' => (int)$page_size,
            'data' => []
        ];

    }

    /**
     *
     * 复制一个接口
     *
     * @param integer $id
     *
     * @return array
     */
    public function copy($id)
    {
        $user = $this->user_service->getUser();

        if (!$id) {
            return ['code' => -1];
        }

        $em     = $this->container->get('doctrine')->getManager();
        $rep    = $em->getRepository('RenshanDetectorBundle:Target');

        $target = $rep->find($id);

        if (!($target instanceof TargetEntity)) {
            return ['code' => -1];
        }

        $copied = new TargetEntity;

        $copied->setUrl($target->getUrl());
        $copied->setTitle($target->getTitle() . ' (复制)');
        $copied->setMethod($target->getMethod());
        $copied->setTimes($target->getTimes());
        $copied->setHeaders($target->getHeaders());
        $copied->setParameters($target->getParameters());
        $copied->setUser($user);

        $em->persist($copied);
        $em->flush();

        return ['code' => 1];
    }

    /**
     *
     * 删除一个接口
     *
     * @param integer id
     *
     * @return array
     */
    public function delete($id)
    {
        if (!$id) {
            return ['code' => -1];
        }

        $em     = $this->container->get('doctrine')->getManager();
        $rep    = $em->getRepository('RenshanDetectorBundle:Target');

        $target = $rep->find($id);

        if (!($target instanceof TargetEntity)) {
            return ['code' => -1];
        }

        $results = $target->getResults();

        foreach ($results as $result) {
            $em->remove($result);
        }

        $em->remove($target);
        $em->flush();

        return ['code' => 1];
    }


    /**
     *
     * 更新一个探测接口
     *
     * @param   integer         $id
     * @param   string          $title
     * @param   string          $url
     * @param   string          $method
     * @param   array           $headers
     * @param   array           $parameters
     *
     * @return  TargetEntity    $target
     */
    public function update($id, $title, $url, $method = 'GET', $timing, $headers = [], $parameters = [])
    {
        if (!$id) {
            return ['code' => -1];
        }

        $em     = $this->container->get('doctrine')->getManager();
        $rep    = $em->getRepository('RenshanDetectorBundle:Target');

        $target = $rep->find($id);

        if (!($target instanceof TargetEntity)) {
            return ['code' => -1];
        }


        $target->setTitle($title);
        $target->setUrl($url);
        $target->setMethod($method);
        $target->setTiming($timing);
        $target->setHeaders($headers);
        $target->setParameters($parameters);

        $em = $this->container->get('doctrine')->getManager();
        $em->persist($target);
        $em->flush();

        return ['code' => 1];
    }

    /**
     *
     * 查询某个用户下面的所有接口
     *
     * @return array
     */
    public function getAll()
    {
        $user = $this->user_service->getUser();

        $em     = $this->container->get('doctrine')->getManager();
        $query  = $em->createQuery("SELECT t.id, t.title FROM Renshan\DetectorBundle\Entity\Target t WHERE t.user = ?1");

        $query->setParameter(1, $user);

        return $query->getArrayResult();
    }

    /**
     *
     * 删除一个接口
     *
     * @param integer   $id
     *
     * @return array
     */
    public function detect($id)
    {
        $user = $this->user_service->getUser();

        if (!$id) {
            return ['code' => -1];
        }

        $em     = $this->container->get('doctrine')->getManager();
        $rep    = $em->getRepository('RenshanDetectorBundle:Target');

        $target = $rep->find($id);

        if (!$target) {
            return ['code' => -1];
        }

        if ($target->getUser()->getId() !== $user->getId()) {
            return ['code' => -1];
        }


        $headers = new Headers;

        $headers_array = $target->getHeaders();

        foreach ($headers_array as $k => $v) {
            $headers->set($k, $v);
        }

        $this->target = $target;

        $request = new Request($target->getUrl(), $target->getMethod(), $headers, $target->getParameters(), 1);

        $request->setBeforeSend(function($time) {
            $this->beforeSend($time);
        });

        $request->setAfterSend(function($time, $response) {
            $this->afterSend($time, $response);
        });

        $request->setAfterComplete(function() {
            $this->complete();
        });

        $request->send();

        $results = [];

        foreach ($this->results as $result) {
            $tmp = [];

            $tmp['duration']    = $result->getDuration();
            $tmp['satus_code']  = $result->getStatusCode();
            //$tmp['body']        = $result->getBody();
            $tmp['headers']     = $result->getHeaders();

            array_push($results, $tmp);
        }

        return ['code' => 1, 'results' => $results];
    }

    /**
     * 每次发起请求前的匿名函数, 匿名函数接收一个参数
     *
     * @param integer   $time
     *
     */
    public  function beforeSend($time)
    {
    }

    /**
     * 每次请求后的匿名函数, 匿名函数接收两个参数
     *
     * @param   integer   $time
     * @param   Renshan\Http\Response $response
     *
     */
    public function afterSend($time, $response)
    {

        $result = new ResultEntity;

        $result->setBody($response->getBody());
        $result->setHeaders($response->getHeaders()->getAll());
        $result->setStatusCode($response->getStatusCode());
        $result->setDuration($response->getRequestTime());
        $result->setTime(new \DateTime());
        $result->setTarget($this->target);

        array_push($this->results, $result);
    }

    /**
     * 所有请求完成后的匿名函数
     */
    public function complete()
    {
        $em = $this->container->get('doctrine')->getManager();

        foreach ($this->results as $result) {
            $em->persist($result);
        }

        $em->flush();
    }
}
